/*
 * Copyright 2012-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package keter.sec.xss.controller;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;

@Controller
public class XssController {
	private static final Logger logger = LoggerFactory.getLogger(XssController.class);

	@GetMapping("/")
	public void welcome(HttpServletRequest request,HttpServletResponse response) throws IOException {
//		return "index";
		response.sendRedirect("/mystatic/index.html");
	}

	/**
	 * 产生漏洞但未生效：thymeleaf模板解析渲染时统一将特殊字符进行了处理
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	@PostMapping("/xsshtml")
	public String xsshtml(HttpServletRequest request) throws ServletException, IOException{
		String input = request.getParameter("input");
		//问题发生点：字符转义后进行GBK编码，%5c(\)被%df吃进
		input = URLDecoder.decode(input,"GBK");
		System.out.println("output:" + input);
		request.setAttribute("input", input);
		return "xss-result";
	}

	/**
	 * 产生漏洞但未生效：java代码进行URL编码时发生了字符吃进，但thymeleaf模板解析时将引号做了html转义替换
	 * @param request
	 * @author  gulx@neusoft.com
	 * @throws IOException 
	 * @date    2016年12月7日
	 */
	@PostMapping("/xssform")
	public String xsspost(HttpServletRequest request) throws ServletException, IOException{
		String input = request.getParameter("input");
		input = softFilter(input);
	    request.setAttribute("input", input);
	    return "xss-result";
	}

	/**
	 * 不产生漏洞：ajax回调中不会将返回的data组成js代码
	 * @param request
	 * @param response
	 * @return
	 * @author  gulx@neusoft.com
	 * @date    2016年12月7日
	 */
	@PostMapping("/xss")
	@ResponseBody
	public String xssajax(HttpServletRequest request,HttpServletResponse response) throws ServletException{
		String input = request.getParameter("input");
		System.out.println("input:"+input);
		input = softFilter(input);
		return input;
	}

	/**
	 * 不会产生漏洞：undertow中间件无返回结果
	 * @param request
	 * @author  gulx@neusoft.com
	 * @date    2016年12月7日
	 */
	@GetMapping("/xssform")
	public void xssget(HttpServletRequest request) throws ServletException, IOException {
		xsspost(request);
	}
	
	private String softFilter(String   input) {
		System.out.println("input:"+input);
		if(input.contains("\"") || input.contains("%22")){
			input = input.replace("%22", "%5c%22");
			input = input.replace("\"", "%5c%22");
		}
		if(input.contains("<") || input.contains(">")){
			input = input.replace("<", "&lt;");
			input = input.replace(">", "&gt;");
		}
		System.out.println("output before decode:"+input);
		//问题发生点：字符转义后进行GBK编码，%5c(\)被%df吃进
		try {
			input = URLDecoder.decode(input,"GBK");
          //input = URLDecoder.decode(input);//使用默认字符集转义不一定出问题

		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		System.out.println("output decoded:"+input);
		return input; 
	}

	@GetMapping("/result")
	public String result(HttpServletRequest request) throws ServletException, IOException{
		logger.info("param:{}",request.getParameter("param"));
		request.setAttribute("input", "input");
		return "xss-result";
	}

}
